package com.iwhalecloud.uncc.dao.impl;

import java.sql.Connection;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Repository;

import com.iwhalecloud.uncc.dao.SysConfigDao;
import com.iwhalecloud.uncc.model.MqClusterConfig;
import com.iwhalecloud.uncc.model.RedisConfig;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Repository("sysConfigDao")
@ConditionalOnProperty(name = "loadFromDb", havingValue = "true", matchIfMissing = true)
public class SysConfigDaoImpl implements SysConfigDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Cacheable(value = "pbIsppConfig", key = "#code")
	@Override
	public String getSysConfig(String code) {
		String sql = "select value from pb_ispp_config where code=? ";
		List<String> valueList = this.jdbcTemplate.queryForList(sql, new Object[] { code }, String.class);
		if (!valueList.isEmpty()) {
			return valueList.get(0);
		}
		return null;
	}

	@Override
	@Cacheable(value = "moduleConfig", key = "#module+'-'+#appName+'-'+#code")
	public String getModuleConfig(String module, String appName, String code) {
		String sql = "SELECT MODULE, APP_NAME, CODE, VALUE, COMMENTS FROM ISAP_MODULE_PRO_CONFIG WHERE MODULE=? AND APP_NAME=? AND CODE=?";
		List<Map<String, Object>> list = this.jdbcTemplate.queryForList(sql, new Object[] { module, appName, code });
		String result = "";
		if (list != null && !list.isEmpty()) {
			result = (String) list.get(0).get("VALUE");
			if (result == null) {
				return "";
			}
		}
		return result;
	}

	@Cacheable(value = "redisConfig", key = "#clusterCode")
	@Override
	public RedisConfig getRedisConfig(String clusterCode) {
		String sql = "select rc_id, rc_code, template_code, host_port, db, username, pwd, period, "
				+ "monitor_timeout, pool_properties from uc_redis_config where template_code = ?";
		List<RedisConfig> list = this.jdbcTemplate.query(sql, new Object[] { clusterCode },
				BeanPropertyRowMapper.newInstance(RedisConfig.class));

		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	@Cacheable(value = "clusterConfig", key = "#clusterCode")
	@Override
	public MqClusterConfig getMqClusterConfig(String clusterCode) {
		String sql = "select M.NAMESERV, M.TENANT_ID,M.USERNAME, M.PWD, M.CLUSTER_NAME, M.MQ_CODE, M.SEND_TIMEOUT FROM uc_mq_config M "
				+ " WHERE M.MQ_CODE=? ";
		List<MqClusterConfig> list = this.jdbcTemplate.query(sql, new Object[] { clusterCode },
				BeanPropertyRowMapper.newInstance(MqClusterConfig.class));

		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public List<Long> getCtgSeq(String seqName, int batchSize) {
		String sql = "SELECT " + seqName + ".NEXTVAL(" + batchSize + ")";
		List<Long> seqList = this.jdbcTemplate.queryForList(sql, Long.class);
		return seqList;
	}

	@Override
	public Long getLocalSeq(String seqName, int batchSize) {
		try {
			Connection conn = null;
			try {
				conn = jdbcTemplate.getDataSource().getConnection();
			} catch (Exception e) {
				log.error(ExceptionUtils.getStackTrace(e));
			}
			if (conn == null) {
				return null;
			}
			try {
				conn.setAutoCommit(false);
				String sql1 = "SELECT CUR_VALUE FROM SEQUENCE A WHERE A.SEQ_NAME= ? FOR UPDATE";
				List<Long> list = jdbcTemplate.queryForList(sql1, Long.class, new Object[] { seqName });
				Long curValue = null;
				Long nextValue = null;
				if (list != null && !list.isEmpty()) {
					curValue = list.get(0);
				}
				if (curValue == null) {
					throw new Exception("Get CUR_VALUE ERROR! SEQ_NAME:" + seqName);
				} else {
					nextValue = curValue + batchSize;
				}
				String updateSql = "UPDATE SEQUENCE A SET A.CUR_VALUE = ? WHERE SEQ_NAME= ? ";
				this.jdbcTemplate.update(updateSql, new Object[] { nextValue, seqName });
				conn.commit();
				return curValue;
			} catch (Throwable e) {
				log.error("Error occured, cause by: " + ExceptionUtils.getStackTrace(e));
				conn.rollback();
			} finally {
				conn.setAutoCommit(true);
				if (conn != null) {
					conn.close();
				}
			}
		} catch (Exception e) {
			log.error(ExceptionUtils.getStackTrace(e));
		}
		return null;
	}

	@Override
	public Long getSimpleSeq(String seqName) {
		String sql = "SELECT " + seqName + ".NEXTVAL FROM DUAL";
		Long seq = this.jdbcTemplate.queryForObject(sql, Long.class);
		return seq;
	}

	@Override
	@CacheEvict(value = "pbIsppConfig", allEntries = true)
	public void flushSysConfig() {

	}

	@Override
	@CacheEvict(value = "moduleConfig", allEntries = true)
	public void flushModuleConfig() {

	}

	@Override
	public SqlRowSet readSqlRowSet(String sql, Object[] sps) {
		sql = StringEscapeUtils.escapeSql(sql);
		SqlRowSet sqlRowSet = this.jdbcTemplate.queryForRowSet(sql, sps);
		return sqlRowSet;

	}
}
